package com.msb.mall.product.web;

import com.msb.mall.product.entity.CategoryEntity;
import com.msb.mall.product.entity.vo.Catalog2Vo;
import com.msb.mall.product.service.CategoryService;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;
import java.util.UUID;

@Controller
public class IndexController {

    @Autowired
    CategoryService categoryService;

    @Autowired
    RedissonClient redissonClient;
    @Autowired
    StringRedisTemplate redisTemplate;
    @GetMapping({"/","/index","/home"})
    public String index(Model model){
        //查询出所有的一级分类信息
        List<CategoryEntity>  categorys= categoryService.getLevelCateGory();
        model.addAttribute("categorys",categorys);
        //classPath:/templates/
        //.html
        return "index";
    }

    @ResponseBody
    @RequestMapping ("/index/catalog.json")
    public Map<String, List<Catalog2Vo>> getCateLog2Json(){
        return categoryService.getCateLog2Json();
    }

    /**
     * 1.锁会自动续期，如果业务时间超长，运行期间Redisson会自动给锁重新添加30s，不用担心业务时间，锁自动过去而造成的数据安全问题
     * 2.加锁的业务只要执行完成， 那么就不会给当前的锁续期，即使我们不去主动的释放锁，锁在默认30s之后也会自动的删除
     * @return
     */
    @ResponseBody
    @GetMapping ("/hello")
    public String  hello(){
        RLock hello = redissonClient.getLock("hello");
        //加锁操作
        hello.lock();
        //指定了过期时间后，自动续期就不会再生效，这时就需要注意设置过期时间要满足业务场景
        //实际开发中发现最后指定过期时间 -->性能考虑
        try {
            System.out.println("加锁成功 = " + Thread.currentThread().getName());
            System.out.println("hello = " + hello);
            Thread.sleep(10000);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            System.out.println("释放锁成功1 = " + Thread.currentThread().getName());
            //释放锁
            hello.unlock();
            System.out.println("释放锁成功2 = " + Thread.currentThread().getName());
        }

        return "hello";
    }


    @ResponseBody
    @GetMapping ("/writer")
    public String  writerValue(){
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("wr-lock");
        //加写锁
        RLock rLock = readWriteLock.writeLock();
        String uuid = null;
        rLock.lock();
        try {
            uuid = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set("msg",uuid);
            Thread.sleep(30000);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            rLock.unlock();
        }
        return uuid;
    }


    @ResponseBody
    @GetMapping ("/read")
    public String  readValue(){
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("wr-lock");
        RLock rLock = readWriteLock.readLock();
        rLock.lock();
        String s = null;
        try {
            s = redisTemplate.opsForValue().get("msg");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            rLock.unlock();
        }

        return s;
    }
}
